NVIC_INT_CTRL    EQU         0xE000ED04    ; Address of NVIC Interruptions Control Register
NVIC_PENDSVSET   EQU         0x10000000    ; Enable PendSV
NVIC_SYSPRI14    EQU         0xE000ED22    ; System priority register (priority 14).
NVIC_PENDSV_PRI  EQU         0xFF          ; PendSV priority value (lowest).


	IMPORT  g_OSTcbCurrentPt ;当前使用的任务TCB
    IMPORT  g_OSTcbNextPt ; 下一个优先级最高的任务TCB
    IMPORT  g_OSExceptStackBasePt  ; MSP堆栈指针
	IMPORT	g_OSRuningFlag ; 任务运行的标志指针
    
	EXPORT	OS_ENTER_CRITICAL
	EXPORT	OS_EXIT_CRITICAL
    EXPORT  OSStart ;启动操作系统
    EXPORT  PendSV_Handler ;PendSv中断
    EXPORT  OSCtxSw ;启动一次任务切换
    
	PRESERVE8	;align 8
	AREA	|.text|, CODE, READONLY
	THUMB

OSCtxSw
	PUSH	{R4,R5}					;最后确定是否需要这样做
    LDR     R0, =NVIC_INT_CTRL      ; R4=NVIC_INT_CTRL
    LDR     R1, =NVIC_PENDSVSET     ; R5=NVIC_PENDSVSET
    STR     R1, [R0]
	POP		{R4,R5}					;最后确定是否需要这样做
	BX		LR

OS_ENTER_CRITICAL
	CPSID	I
	BX		LR
	
OS_EXIT_CRITICAL
	CPSIE	I
	BX		LR
 
OSStart
    ; disable interruptions
    CPSID   I                       ;OS_ENTER_CRITICAL();
    
    ; initialize PendSV
    ; Set the PendSV exception priority
    LDR     R0, =NVIC_SYSPRI14      ; R0=NVIC_SYSPRI14
    LDR     R1, =NVIC_PENDSV_PRI    ; R1=NVIC_PENDSV_PRI
    STRB    R1, [R0]                ; *R0 = R1
    
    ; initialize PSP as 0
    ; MOV R4, #0
    LDR     R4, =0x00               ; R4=0
    MSR     PSP, R4                 ; PSP=R4
    
    ; initialize MSP 可以不用初始化MSP stm32 startUp中已经初始化过
;    LDR     R0, =g_OSExceptStackBasePt ;
;    LDR     R1, [R0]                    ; R1 = g_OSExceptStackBasePt
;    MSR     MSP, R1                     ; 
    
    ; trigger PendSV
    LDR     R4, =NVIC_INT_CTRL      ; R4=NVIC_INT_CTRL
    LDR     R5, =NVIC_PENDSVSET     ; R5=NVIC_PENDSVSET
    STR     R5, [R4]                ; *R4 = R5
    
	LDR		R0, =g_OSRuningFlag			; R0 = osRuningPt
	LDR		R1, =0x01				; R1 = 1
	STR		R1, [R0]				; *R0 = R1	
    ; enable interruptions
    CPSIE   I                       ; OS_EXIT_CRITICAL()

OSStarrtHang
	B       OSStarrtHang             ; 不会运行到这里

PendSV_Handler
    CPSID   I                       ; OS_ENTER_CRITICAL();
    MRS     R0, PSP                 ; R0 = PSP
    CBZ     R0, PendSV_Handler_NoSave   ;if(R0==0){goto PendSV_Handler_NoSave}
    
    STMDB   R0!, {R4-R11}
    
    LDR     R1, =g_OSTcbCurrentPt           ; r1 = g_OSTcbCurrentPt
    LDR     R1, [R1]                ; r1 = *r1
    STR     R0, [R1]                ; *r1 = R0 (*(g_OSTcbCurrentPt->OSTCBStkPrt) = R0)
    
PendSV_Handler_NoSave
    LDR     R0, =g_OSTcbCurrentPt           ; R0 = g_OSTcbCurrentPt
    LDR     R1, =g_OSTcbNextPt          ; R1 = g_OSTcbNextPt
    LDR     R2, [R1]                ; R2 = g_OSTcbNextPt->OSTCBStkPtr R2 = *g_OSTcbNextPt
    STR     R2, [R0]                ; *R0 = R2 g_OSTcbCurrentPt->OSTCBStkPtr = g_OSTcbNextPt->OSTCBStkPtr *R0 = R2 *g_OSTcbCurrentPt = *g_OSTcbNextPt
    LDR     R0, [R2]                ; R0 = *R2 R0 = g_OSTcbNextPt->OSTCBStkPtr 
    LDMIA   R0!, {R4-R11}
    
    MSR     PSP, R0
    
    ORR     LR, LR, #0x04
    CPSIE   I
    BX      LR
	
	align 4
	end